/**
 * Copyright 2015 WalkTheTalkTech, Inc. All rights reserved.
 */
package walkthetalktech.batch;

import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * @author wangshuai
 */
@Component
public class TokenManager {

	/*public static String ServiceNumAppid = PropertyFileReader.getItem("ServiceNumAppid");
    public static String ServiceNumSecret = PropertyFileReader.getItem("ServiceNumSecret");
	public static String SubscriptionNumAppid = PropertyFileReader.getItem("SubscriptionNumAppid");
	public static String SubscriptionNumSecret = PropertyFileReader.getItem("SubscriptionNumSecret");
	public static String CorpNumAppid = PropertyFileReader.getItem("CorpNumAppid");
	public static String CorpNumSecret = PropertyFileReader.getItem("CorpNumSecret");*/

    @Value("${stark.servicenum.appid}")
    public String serviceNumAppid;
    @Value("${stark.servicenum.secret}")
    public String serviceNumSecret;
    @Value("${stark.subscriptionnum.appid}")
    public String subscriptionNumAppid;
    @Value("${stark.subscriptionnum.secret}")
    public String subscriptionNumSecret;
    @Value("${stark.corpnumappid}")
    public String corpNumAppid;
    @Value("${stark.corpnumsecret}")
    public String corpNumSecret;

    public static String url_pre = "https://api.weixin.qq.com/cgi-bin/";
    public static String url_pre_qyh = "https://qyapi.weixin.qq.com/cgi-bin/";

    private static Logger logger = LoggerFactory.getLogger(TokenManager.class);

    private static String token;
    private static long expiresIn;

    // 重复周期调用[5秒]

//    @Scheduled(cron = "0 0 * * * ?")
    public void flushToken() throws Throwable {
        logger.info("开始刷新测试服务器号token");
        getToken(serviceNumAppid, serviceNumSecret, 1);
    }

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
//        getToken(serviceNumAppid, serviceNumSecret, 1);
//        getToken(subscriptionNumAppid, subscriptionNumSecret, 2);
//        getToken(corpNumAppid, corpNumSecret, 3);
    }

    public static void getToken(String Appid, String Secret, int id) throws SQLException {
        JSONObject tk = null;
        Connection conn = null;
        token = "";
        expiresIn = 0;
        String url = "";
        if (id == 3) {
            url = url_pre_qyh + "gettoken?corpid=" + Appid + "&corpsecret=" + Secret;
        } else {
            url = url_pre + "token?grant_type=client_credential&appid=" + Appid + "&secret=" + Secret;
        }
        tk = httpRequest(url, "GET", null);

        if (tk == null || !tk.containsKey("access_token")) {
            logger.error("取得AccessToken发生错误。");
            return;
        }

        token = tk.getString("access_token");
        expiresIn = tk.getLong("expires_in");

        logger.info("取得了新的AccessToken.token:" + token + ", 过期时间:" + expiresIn);

        // MySQL的JDBC URL编写方式：jdbc:mysql://主机名称：连接端口/数据库的名称?参数=值
        // 避免中文乱码要指定useUnicode和characterEncoding
        // 执行数据库操作之前要在数据库管理系统上创建一个数据库，名字自己定，
        // 下面语句之前就要先创建javademo数据库
        /*String dbUrl = "jdbc:mysql://rdstew6pbl4xku6u8h0rg.mysql.rds.aliyuncs.com/mavericks?"
                + "user=mavericks&password=hohoTECH123&useUnicode=true&characterEncoding=UTF8";*/
        String dbUrl = "jdbc:mysql://101.201.220.34:3306/mavericks?"
                + "user=mavericks&password=123456&useUnicode=true&characterEncoding=UTF8";
        /*String dbUrl = "jdbc:mysql://localhost:3306/mavericks?user=root&password=yyj&characterEncoding=utf-8";*/
        try {
            // 之所以要使用下面这条语句，是因为要使用MySQL的驱动，所以我们要把它驱动起来，
            // 可以通过Class.forName把它加载进去，也可以通过初始化来驱动起来，下面三种形式都可以
            Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动

            System.out.println("成功加载MySQL驱动程序");
            // 一个Connection代表一个数据库连接
            conn = DriverManager.getConnection(dbUrl);
            // Statement里面带有很多方法，比如executeUpdate可以实现插入，更新和删除等
            Statement stmt = conn.createStatement();

            String sql = "insert into token_manager(id,token,expires_in,flush_time) values (" + id + ",'"
                    + token
                    + "',"
                    + expiresIn
                    + ","
                    + "now()) on duplicate key update token='"
                    + token
                    + "', expires_in=" + expiresIn + ",flush_time=now();";
            System.out.println(sql);
            int result = stmt.executeUpdate(sql);// executeUpdate语句会返回一个受影响的行数，如果返回-1就没有成功
            if (result != -1) {
                logger.info("成功登录新的AccessToken.token:" + token + ", 过期时间:" + expiresIn);
            }
        } catch (SQLException e) {
            System.out.println("MySQL操作错误");
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.close();
        }

        logger.info("刷新Token处理完成");
    }

    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式（GET、POST）
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpRequest(String requestUrl,
                                         String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url
                    .openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(
                    inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(
                    inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            logger.error("Weixin server connection timed out.");
        } catch (Exception e) {
            logger.error("https request error:{}", e);
        }
        return jsonObject;
    }
}
